package com.redoor.app.stake.basicdata.service.impl;

import com.redoor.app.stake.auth.service.BaseUserService;
import com.redoor.app.stake.basicdata.aop.IgnoreAopLog;
import com.redoor.app.stake.basicdata.dao.SyncOrganizationMapper;
import com.redoor.app.stake.basicdata.model.SyncOrganization;
import com.redoor.app.stake.basicdata.model.UsrDistrict;
import com.redoor.app.stake.basicdata.model.constants.BasicDataRedisConstants;
import com.redoor.app.stake.basicdata.model.controllerModel.SyncOrganizationCriteria;
import com.redoor.app.stake.basicdata.service.SyncOrganizationService;
import com.redoor.app.stake.common.utils.JsonUtils;
import com.redoor.app.stake.common.utils.UUIDTool;
import com.redoornetwork.framework.data.redis.util.RedisUtils;
import com.redoornetwork.framework.mybatis.service.AbstractService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by wangjunlei on 2018-03-05 17:11:50.
 */
@Service
public class SyncOrganizationServiceImpl extends AbstractService<SyncOrganization, String> implements SyncOrganizationService {

    private Logger logger = LoggerFactory.getLogger(SyncOrganizationServiceImpl.class);

    public static final String REDIS_ORGAN_KEY = "ORGANIZATION:";

    public static final String REDIS_DISTRICT_KEY = "DISTRICT:";

    @Autowired
    private SyncOrganizationMapper syncOrganizationMapper;
    @Autowired
    private BaseUserService baseUserService;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public void initOrganizationToRedis(boolean isDistraint) {
        if(isDistraint){
            logger.info("remove orgs key...");
            redisUtils.removePattern(REDIS_ORGAN_KEY);
        }
        SyncOrganizationCriteria params = new SyncOrganizationCriteria();
        List<SyncOrganization> allList = syncOrganizationMapper.findOrganizationByCondition(params);
        if(allList == null || allList.size() == 0){
            logger.warn("org list is empty...");
            return;
        }

        Map<String,List<SyncOrganization>> treeMap = new HashMap<>();
        for (SyncOrganization org:allList) {
            String orgcode = org.getOrgno();
            if(org.getStatus() != 1000 || StringUtils.isBlank(orgcode)){
                continue;
            }
            redisUtils.set(REDIS_ORGAN_KEY+orgcode,org);

            String parentcode = org.getParentorgno();
            if(StringUtils.isBlank(parentcode)){
                parentcode = "";
            }
            List<SyncOrganization> childList;
            if(treeMap.containsKey(parentcode)){
                childList = treeMap.get(parentcode);
            } else {
                childList = new ArrayList<>();
            }
            childList.add(org);
            treeMap.put(parentcode,childList);
        }

        Iterator<String> it = treeMap.keySet().iterator();
        while (it.hasNext()){
            String code = it.next();
            logger.info("{} set to redis",code);
            redisUtils.hset(REDIS_ORGAN_KEY,code, JsonUtils.toJson(treeMap.get(code)));
        }
    }

    public void initDistrictIntoRedis(boolean isDistraint){
        if(isDistraint){
            logger.info("remove orgs key...");
            redisUtils.removePattern(REDIS_DISTRICT_KEY);
        }
        List<UsrDistrict> allList = syncOrganizationMapper.listAllDistrict();
        if(allList == null || allList.size() == 0){
            logger.warn("org list is empty...");
            return;
        }

        Map<String,List<UsrDistrict>> treeMap = new HashMap<>();
        for (UsrDistrict org:allList) {
            String orgcode = org.getCode();
            redisUtils.set(REDIS_DISTRICT_KEY+orgcode,org);
            String parentcode = "";
            if("3".equalsIgnoreCase(org.getLevel()) ){
                parentcode = org.getCityCode();
            } else if ("2".equalsIgnoreCase(org.getLevel())){
                parentcode = org.getProvinceCode();
            } else {
                parentcode = "0";
            }
            List<UsrDistrict> childList;
            if(treeMap.containsKey(parentcode)){
                childList = treeMap.get(parentcode);
            } else {
                childList = new ArrayList<>();
            }
            childList.add(org);
            treeMap.put(parentcode,childList);
        }

        Iterator<String> it = treeMap.keySet().iterator();
        while (it.hasNext()){
            String code = it.next();
            logger.info("{} set to redis",code);
            redisUtils.hset(REDIS_DISTRICT_KEY,code, JsonUtils.toJson(treeMap.get(code)));
        }
    }

    public List<UsrDistrict> listUsrDistrictAll(){
        List list = new ArrayList();
        if(!redisUtils.exists(REDIS_DISTRICT_KEY+"ALL")){
            list = getDistrictListByParent(null,true);
            redisUtils.set(REDIS_DISTRICT_KEY+"ALL",JsonUtils.toJson(list), BasicDataRedisConstants.REDIS_OVER_TIME_DAY);
        } else {
            list = Arrays.asList(JsonUtils.readValue(redisUtils.get(REDIS_DISTRICT_KEY+"ALL").toString(),UsrDistrict[].class));
        }
        return list;
    }

    @Override
    public String getDistrictName(String code) {
        UsrDistrict usrDistrict = null;
        if(StringUtils.isBlank(code)){
            return "";
        }
        if(redisUtils.exists(REDIS_DISTRICT_KEY+code)){
            usrDistrict = (UsrDistrict) redisUtils.get(REDIS_DISTRICT_KEY+code);
            return usrDistrict.getName();
        }
        return "";
    }

    @Override
    public int inserOrUpdateByOrgNoToSyncOrganization(SyncOrganization syncOrganization) {
        if(syncOrganization == null || StringUtils.isBlank(syncOrganization.getOrgno())){
            return 0;
        }
        int result = this.syncOrganizationMapper.inserOrUpdateByOrgNoToSyncOrganization(syncOrganization);

        //更新缓存
        redisUtils.set(REDIS_ORGAN_KEY+syncOrganization.getOrgno(),syncOrganization);
        List<SyncOrganization> treelist;
        if(redisUtils.hHasKey(REDIS_ORGAN_KEY,syncOrganization.getOrgno())){
            treelist = Arrays.asList(JsonUtils.readValue(redisUtils.hget(REDIS_ORGAN_KEY,syncOrganization.getOrgno()).toString(),SyncOrganization[].class));
        } else {
            treelist = new ArrayList<>();
        }
        treelist.add(syncOrganization);
        redisUtils.hset(REDIS_ORGAN_KEY,syncOrganization.getOrgno(), JsonUtils.toJson(treelist));
        return result;
    }

    @Override
    public String getCityOrgNoByAnOrgNo(String orgNo) {
        if(StringUtils.isBlank(orgNo)){
            return null;
        }
        /*长度为7是省级别组织机构编码,返回null*/
        if(7 == orgNo.length()){
            return null;
        }
        /*长度为10是地市级组织机构编码,直接返回结果*/
        if (10 == orgNo.length()){
            return orgNo;
        }
        /*长度为13为部门级别组织机构编码,返回父级组织机构编码*/
        if (13 == orgNo.length()){
            SyncOrganization partOrganization = this.get(orgNo);
            if (null == partOrganization) return null;

            SyncOrganization cityOrganization = this.get(partOrganization.getParentorgno());
            if (null == cityOrganization) return null;

            return cityOrganization.getOrgno();
        }
        return null;
    }

    @Override
    public String getProvinceOrgNoByAnOrgNo(String orgNo) {
        if(StringUtils.isBlank(orgNo)){
            return null;
        }
        /*长度为7是省级别组织机构编码,直接返回结果*/
        if(7 == orgNo.length()){
            return orgNo;
        }
        /*长度为10是地市级组织机构编码,返回父级组织机构编码*/
        if (10 == orgNo.length()){
            SyncOrganization cityOrganization = this.get(orgNo);
            if (null == cityOrganization) return null;

            SyncOrganization proOrganization = this.get(cityOrganization.getParentorgno());
            if (null == proOrganization) return null;

            return proOrganization.getOrgno();
        }
        /*长度为13为部门级别组织机构编码,返回父级的父级组织机构编码*/
        if (13 == orgNo.length()){
            SyncOrganization partOrganization = this.get(orgNo);
            if (null == partOrganization) return null;

            SyncOrganization cityOrganization = this.get(partOrganization.getParentorgno());
            if (null == cityOrganization) return null;

            SyncOrganization proOrganization = this.get(cityOrganization.getParentorgno());
            if (null == proOrganization) return null;

            return proOrganization.getOrgno();
        }
        return null;
    }

    private List<UsrDistrict> getDistrictListByParent(List<UsrDistrict> lists,boolean isroot){

        List<UsrDistrict> result = new ArrayList<>();
        if(lists == null && isroot){
            if(!redisUtils.exists(REDIS_DISTRICT_KEY+"0")){
                initDistrictIntoRedis(true);
            }
            lists = Arrays.asList(JsonUtils.readValue(redisUtils.hget(REDIS_DISTRICT_KEY,"0").toString(),UsrDistrict[].class));
            result.addAll(lists);
        }

        for (UsrDistrict org:lists) {
            if(redisUtils.hHasKey(REDIS_DISTRICT_KEY,org.getCode())){
                List<UsrDistrict> chilList = Arrays.asList(JsonUtils.readValue(redisUtils.hget(REDIS_DISTRICT_KEY,org.getCode()).toString(),UsrDistrict[].class));
                if(chilList!=null && chilList.size()>0){
                    result.addAll(chilList);
                    result.addAll(getDistrictListByParent(chilList,false));
                }
            }
        }
        return result;
    }

    @Override
    public int deleteByOrgNo(String orgNo) {
        if(StringUtils.isBlank(orgNo)){
            return 0 ;
        }
        SyncOrganizationCriteria params = new SyncOrganizationCriteria();
        params.setOrgNo(orgNo);
        int result = syncOrganizationMapper.deleteOrganization(params);

        if(redisUtils.exists(REDIS_ORGAN_KEY+orgNo)){
            SyncOrganization organization = (SyncOrganization) redisUtils.get(REDIS_ORGAN_KEY+orgNo);
            String parentOrg = organization.getParentorgno();
            redisUtils.hdel(REDIS_ORGAN_KEY,parentOrg);

            redisUtils.remove(REDIS_ORGAN_KEY+orgNo);
        }
        return result;
    }

    @Override
    public void updateByOrgNo(SyncOrganizationCriteria syncOrganizationCriteria) {
        SyncOrganization organization = new SyncOrganization();
        organization.setOrgno(syncOrganizationCriteria.getOrgNo());
        organization.setParentorgno(syncOrganizationCriteria.getParentOrgNo());
        organization.setName(syncOrganizationCriteria.getName());
        organization.setStandardcode(syncOrganizationCriteria.getStandardCode());

        String orgNo = organization.getOrgno();
        SyncOrganization oldOrg = get(orgNo);

        if(StringUtils.isBlank(organization.getParentorgno())){
            organization.setParentorgno("0");
        } else {
            SyncOrganization parentOrg = get(organization.getParentorgno());
            organization.setParentorguuid(parentOrg.getUuid());
        }

        if(oldOrg == null){
            oldOrg = organization;
            oldOrg.setUuid(UUIDTool.getUUID());
            oldOrg.setCreatedat(new Date());
            this.save(oldOrg);
        } else {
            oldOrg.setName(organization.getName());
            oldOrg.setParentorgno(organization.getParentorgno());
            oldOrg.setUpdatedat(new Date());
            this.updateBySelective(oldOrg);
        }

        redisUtils.set(REDIS_ORGAN_KEY+orgNo,oldOrg);
        redisUtils.hdel(REDIS_ORGAN_KEY,oldOrg.getParentorgno());
    }

    @Override
    public List<SyncOrganization> findByParentOrgNo(String parentNo) {
        if(StringUtils.isBlank(parentNo)){
            return null;
        }
        if(redisUtils.hHasKey(REDIS_ORGAN_KEY,parentNo)){
            return Arrays.asList(JsonUtils.readValue(redisUtils.hget(REDIS_ORGAN_KEY,parentNo).toString(),SyncOrganization[].class));
        } else {
            SyncOrganizationCriteria params = new SyncOrganizationCriteria();
            params.setParentOrgNo(parentNo);
            List<SyncOrganization> list = syncOrganizationMapper.findOrganizationByCondition(params);
            redisUtils.hset(REDIS_ORGAN_KEY,parentNo, JsonUtils.toJson(list));
            return list;
        }
    }

    @Override
    public List<SyncOrganization> getAllList(List<SyncOrganization> lists,boolean isroot) {
        List<SyncOrganization> result = new ArrayList<>();
        //如果是根节点并且查询列表为空则查询3下所有以及节点集合
        if(null == lists && isroot){
            lists = findByParentOrgNo("3");
            result.addAll(lists);
        }

        for (SyncOrganization org:lists) {
            List<SyncOrganization> chilList = findByParentOrgNo(org.getOrgno());
            if(chilList!=null && chilList.size()>0){
                result.addAll(chilList);
                result.addAll(getAllList(chilList,false));
            }
        }
        return result;
    }


    @Override
    public SyncOrganization get(String orgNo) {
        if(StringUtils.isBlank(orgNo)){
            return null;
        }
        SyncOrganization syncOrganization = null;
        if(redisUtils.exists(REDIS_ORGAN_KEY+orgNo)){
            syncOrganization = (SyncOrganization) redisUtils.get(REDIS_ORGAN_KEY+orgNo);
        } else {
            SyncOrganizationCriteria params = new SyncOrganizationCriteria();
            params.setOrgNo(orgNo);
            List<SyncOrganization> list = syncOrganizationMapper.findOrganizationByCondition(params);
            if(list != null && list.size()>0){
                syncOrganization = list.get(0);
            }
        }
        return syncOrganization;
    }

    public SyncOrganization getOrganizationByPk(String uuid){
        if(StringUtils.isBlank(uuid)){
            return null;
        }
        return syncOrganizationMapper.selectByPrimaryKey(uuid);
    }

    @IgnoreAopLog
    @Override
    public String getFullOrgName(String orgNo) {
        if(StringUtils.isBlank(orgNo)){
            return "";
        }
        if(redisUtils.exists(SyncOrganizationServiceImpl.REDIS_ORGAN_KEY+orgNo)){
            SyncOrganization organization = (SyncOrganization) redisUtils.get(SyncOrganizationServiceImpl.REDIS_ORGAN_KEY+orgNo);
            if(organization!=null && !"3".equalsIgnoreCase(organization.getParentorgno()) && !StringUtils.isBlank(organization.getParentorgno())){
                return getFullOrgName(organization.getParentorgno())+"-"+organization.getName();
            } else {
                return organization.getName();
            }
        }
        return "";
    }
}
